//
// Created by mio on 25-4-11.
//

#ifndef TIMER_H
#define TIMER_H

#include <unordered_map>
#include <map>
#include <thread>
#include <memory>
#include <functional>
#include <cstdint>
#include <mutex>

using TimerEvent = std::function<bool(void)>;
using TimerId = uint32_t;

class Timer {
public:
    Timer(const TimerEvent& event, uint32_t msec) : eventCallback_(event), interval_(msec) {}
    ~Timer() = default;

    /**
     * @brief 静态工具函数，让当前线程休眠指定的毫秒数。
     * @param msec 要休眠的毫秒数。
     */
    static void Sleep(uint32_t msec)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(msec));
    }

private:
    /**
     * @brief 设置下一次超时时间点。
     * 基于给定的参考时间点 `time_point` 加上定时器的间隔 `interval_`。
     * @param time_point 计算下一次超时的基准时间点（通常是当前时间或上一次超时时间）。
     */
    inline void SetNextTimeout(int64_t time_point) { next_timeout_ = time_point + interval_; }
    /**
     * @brief 获取已计算好的下一次超时时间点。
     * @return 下一次超时时间点（毫秒级时间戳）。
     */
    inline int64_t GetNextTimeout() const { return next_timeout_; }
    friend class TimerQueue;

private:
    TimerEvent eventCallback_ = []{ return false; };
    uint32_t interval_ = 0;         // 定时器间隔（毫秒）
    int64_t next_timeout_ = 0;      // 下一次超时绝对时间点（毫秒级时间戳，基于 steady_clock）
};

/**
 * @brief 管理一系列 Timer 对象的队列。
 * 负责添加、删除定时器，并在适当的时间触发定时器事件。
 */
class TimerQueue
{
public:
    /**
     * @brief 添加一个新的定时器到队列中。
     * @param event 定时器触发时执行的回调函数。
     * @param msec 定时器的间隔或延迟（毫秒）。
     * @return 新添加的定时器的唯一 ID (TimerId)。
     */
    TimerId AddTimer(const TimerEvent& event, uint32_t msec);
    /**
     * @brief 从队列中移除一个指定 ID 的定时器。
     * @param timerid 要移除的定时器的 ID。
     */
    void RemoveTimer(TimerId timerid);
    /**
     * @brief 处理当前到期的所有定时器事件。
     * 应在事件循环中定期调用此方法。
     */
    void HandleTimerEvent();

    int64_t GetTimeRemaining();

private:
    /**
     * @brief 获取当前时间点（基于 steady_clock，返回毫秒级时间戳）。
     * @return 当前时间的毫秒级时间戳 (int64_t)。
     */
    int64_t GetTimeNow();
    // 使用 unordered_map 存储 TimerId 到 Timer 智能指针的映射
    // 提供通过 TimerId 快速查找 O(1) 和删除 Timer 的能力。
    std::unordered_map<TimerId, std::shared_ptr<Timer>> timers_;
    // 使用 map 存储 <超时时间点, TimerId> 到 Timer 智能指针的映射
    // `std::map` 会自动根据 key (即超时时间点) 排序，使得 events_.begin() 总是指向最近将要超时的定时器。
    // 使用 pair<int64_t, TimerId> 作为 key 是为了处理多个定时器在同一毫秒超时的情况，保证唯一性。
    std::map<std::pair<int64_t, TimerId>, std::shared_ptr<Timer>> events_;
    // 用于生成唯一的 TimerId
    uint32_t last_timer_id_ = 0;

    std::mutex mtx_;
};

#endif //TIMER_H
